<template>
  <el-input type="string" v-model="numberValue" @blur="unFormart(numberValue)"
            @focus="formart(numberValue)" @input="input"
            :placeholder="placeholder" align="right" precision="4" formart="false">
    <template v-if="this.prepend!=null" #prepend>{{ this.prepend }}</template>
    <template v-if="this.append!=null" #append>{{ this.append }}</template>
  </el-input>
</template>
<script>
import {formartNumber, unFormartNumber, numberPrecision} from '@/utils/numberUtil'
import {isVoid, isNotVoid} from '@/utils/util'
export default {
  emits: ['update:modelValue'],
  props: {
    prepend: {
      type: String,
      default: null
    },
    placeholder: {
      type: String,
      default: '请填写'
    },
    modelValue: Number, // 以前是`value：String`
    append: {
      type: String,
      default: null,
    },
    min: {type: String, default: 0},
    max: {type: Number, default: undefined}
  },
  watch: {
    modelValue: {
      handler(v) {
        if (v === this.numberValue) return
        if (!this.checkValid(v)) {
          v = 0
        }
        this.formart(Number(v))
        // this.numberValue = Number(v)
        // this.$emit('update:modelValue', this.numberValue);
      },
      immediate: true
    }
  },
  methods: {
    checkValid(value) {
      const ret = (this.$props.max ? this.$props.max >= Number(value) : true)&& isNotVoid(value)  &&
          ((this.$props.min || this.$props.min == 0) ? this.$props.min <= Number(value) : true)
      return ret
    },
    input(v) {
      this.numberValue = v
      this.$emit('update:modelValue', this.numberValue)
    },
    change(v) {
      this.formart(Number(v))
      // this.numberValue = v
      // this.$emit('update:modelValue', v)
    },
    formart(value) {
      if (!this.checkValid(value)) {
        this.numberValue = 0
      }else {
        if (this.$attrs.formart == 'true') {
          let precision = 2
          //格式化时默认小数位为2位
          if (this.$attrs.precision == undefined || this.$attrs.precision == null || this.$attrs.precision == '') {
            this.$attrs.precision = 2
          } else {
            precision = this.$attrs.precision
          }
          this.numberValue = formartNumber(value, precision)
        } else {
          this.numberValue = Number(numberPrecision(value, this.$attrs.precision))
        }
      }
      this.$emit('update:modelValue', this.numberValue)
    },
    unFormart(value) {
      if (!this.checkValid(value)) {
        this.numberValue = this.min
      }else {
        // if (this.$attrs.formart == 'true') {
        this.numberValue = numberPrecision(Number(value), this.$attrs.precision)
      }
      this.$emit('update:modelValue', this.numberValue)
      // }
    }
  },
  data() {
    return {
      numberValue: null
    }
  }
}

/**
 * 重写 Number.prototype.toFixed() 方法
 * 解决四舍五入问题
 * @param n 四舍五入位数
 */
// Number.prototype.toFixed = function (n) {
//   const number = this
//   // 如果 digits 参数太小或太大。0 到 20（包括）之间的值不会引起 RangeError。实现环境（implementations）也可以支持更大或更小的值
//   if (n > 20 || n < 0) {
//     throw new RangeError('toFixed() digits argument must be between 0 and 20')
//   }
//   // 如果该方法在一个非Number类型的对象上调用
//   if (isNaN(number)) {
//     throw new TypeError(number + '.toFixed() is not a function')
//   }
//   // 如果数值大于 1e+21，该方法会简单调用 Number.prototype.toString()并返回一个指数记数法格式的字符串
//   if (number >= Math.pow(10, 21)) {
//     return number.toString()
//   }
//   // 如果忽略该参数，则默认为 0，进行四舍五入，不包括小数部分
//   if (n === undefined || n === 0) {
//     return Math.round(number).toString()
//   }

//   let result = number.toString()
//   const arr = result.split('.')
//   // 整数情况
//   if (arr.length < 2) {
//     result += '.'
//     for (let i = 0; i < n; i ++) {
//       result += '0'
//     }
//     return result
//   }

//   // 小数情况（原位数 <= 需求位数）
//   const integer = arr[0]
//   let decimal = arr[1]
//   if (decimal.length === n) {
//     return result
//   }
//   if (decimal.length < n) {
//     for (let i = 0; i < n - decimal.length; i++) {
//       result += '0'
//     }
//     return result
//   }
//   // 小数情况（原位数 > 需求位数，需四舍五入）
//   result = integer + '.' + decimal.substring(0, n)
//   const last = decimal.substring(n, n+1)
//   if (parseInt(last, 10) >= 5) {
//     const multiple = Math.pow(10, n)
//     result = ((Math.round(parseFloat(result) * multiple) + 1) / multiple).toString() // 使用 Math.round 防止结果无限小数
//     // 0 补足小数
//     decimal = result.split('.')[1]
//     if (decimal.length < n) {
//       for (let i = 0; i < n - decimal.length; i++) {
//         result += '0'
//       }
//       return result
//     }
//   }
//   return result
// }
//重写Number的toFixed方法，解决四舍五入精度问题
Number.prototype.toFixed=function (d) {
    var s=this+""; 
    if(!d){
    	d=0;
    }else{
    	d=parseInt(d);
    }
    if(s.indexOf(".")==-1)s+="."; 
    s+=new Array(d+1).join("0"); 
    if(new RegExp("^(-|\\+)?(\\d+(\\.\\d{0,"+(d+1)+"})?)\\d*$").test(s)){
        var s="0"+RegExp.$2,pm=RegExp.$1,a=RegExp.$3.length,b=true;
        if(a==d+2){
            a=s.match(/\d/g); 
            if(parseInt(a[a.length-1])>4){
                for(var i=a.length-2;i>=0;i--){
                    a[i]=parseInt(a[i])+1;
                    if(a[i]==10){
                        a[i]=0;
                        b=i!=1;
                    }else break;
                }
            }
            s=a.join("").replace(new RegExp("(\\d+)(\\d{"+d+"})\\d$"),"$1.$2");
        }
        if(b)s=s.substr(1); 
        return (pm+s).replace(/\.$/,"");
    }return this+"";
};

</script>
